रिसोर्स लोडिंगमधील चुका चांगल्याप्रकारे हाताळण्यासाठी हुक्ससह रिएक्ट एरर बाउंड्रीज कसे लागू करायचे ते शिका, ज्यामुळे वापरकर्त्याचा अनुभव आणि ऍप्लिकेशनची स्थिरता सुधारेल.
रिएक्टमध्ये मजबूत रिसोर्स लोडिंग: हुक्ससह एरर बाउंड्रीजमध्ये प्राविण्य मिळवणे
आधुनिक वेब ऍप्लिकेशन्समध्ये, रिसोर्सेस असिंक्रोनस पद्धतीने लोड करणे ही एक सामान्य प्रथा आहे. एपीआय (API) मधून डेटा मिळवणे असो, इमेजेस लोड करणे असो, किंवा मॉड्यूल्स इम्पोर्ट करणे असो, रिसोर्स लोडिंग दरम्यान संभाव्य चुका हाताळणे वापरकर्त्याच्या चांगल्या अनुभवासाठी महत्त्वाचे आहे. रिएक्ट एरर बाउंड्रीज (React Error Boundaries) त्यांच्या चाइल्ड कंपोनेंट ट्रीमध्ये कुठेही जावास्क्रिप्टमधील चुका पकडण्यासाठी, त्या चुका लॉग करण्यासाठी आणि संपूर्ण ऍप्लिकेशन क्रॅश होण्याऐवजी एक फॉलबॅक यूआय (fallback UI) दाखवण्यासाठी एक यंत्रणा प्रदान करतात. हा लेख रिसोर्स लोडिंगमधील चुका व्यवस्थापित करण्यासाठी रिएक्ट हुक्सच्या (React Hooks) सोबत एरर बाउंड्रीजचा प्रभावीपणे कसा वापर करायचा हे स्पष्ट करतो.
एरर बाउंड्रीज समजून घेणे
रिएक्ट 16 पूर्वी, कंपोनेंट रेंडरिंग दरम्यान न हाताळलेल्या जावास्क्रिप्ट चुकांमुळे रिएक्टची अंतर्गत स्थिती बिघडत असे आणि त्यानंतरच्या रेंडरमध्ये अनाकलनीय चुका दिसून येत. एरर बाउंड्रीज त्यांच्या चाइल्ड कंपोनेंट्समध्ये होणाऱ्या चुकांसाठी 'कॅच-ऑल' ब्लॉक म्हणून काम करून ही समस्या सोडवतात. ते असे रिएक्ट कंपोनेंट्स आहेत जे खालीलपैकी एक किंवा दोन्ही लाइफसायकल मेथड्स लागू करतात:
static getDerivedStateFromError(error): ही स्टॅटिक मेथड डिसेंडेंट कंपोनेंटद्वारे एरर थ्रो झाल्यावर कॉल केली जाते. तिला थ्रो केलेली एरर एक वितर्क म्हणून मिळते आणि कंपोनेंटची स्थिती अपडेट करण्यासाठी एक व्हॅल्यू परत करते.componentDidCatch(error, info): ही लाइफसायकल मेथड डिसेंडेंट कंपोनेंटद्वारे एरर थ्रो झाल्यावर कॉल केली जाते. तिला थ्रो केलेली एरर एक वितर्क म्हणून मिळते, तसेच कोणत्या कंपोनेंटने एरर थ्रो केली आहे याबद्दल माहिती असलेले एक ऑब्जेक्ट मिळते. आपण याचा वापर एररची माहिती लॉग करण्यासाठी करू शकता.
महत्त्वाची गोष्ट म्हणजे, एरर बाउंड्रीज केवळ रेंडरिंग फेजमध्ये, लाइफसायकल मेथड्समध्ये, आणि त्यांच्या खालील संपूर्ण ट्रीच्या कंस्ट्रक्टर्समध्ये झालेल्या चुका पकडतात. त्या नाहीत खालील गोष्टींसाठी चुका पकडत:
- इव्हेंट हँडलर्स (खालील विभागात अधिक जाणून घ्या)
- असिंक्रोनस कोड (उदा.,
setTimeoutकिंवाrequestAnimationFrameकॉलबॅक्स) - सर्व्हर-साइड रेंडरिंग
- एरर बाउंड्रीमध्येच थ्रो झालेल्या चुका (त्याच्या चाइल्ड कंपोनेंट्समध्ये नव्हे)
एरर बाउंड्रीज आणि रिएक्ट हुक्स: एक शक्तिशाली संयोजन
एरर बाउंड्रीज लागू करण्यासाठी पारंपरिकरित्या क्लास कंपोनेंट्सचा वापर केला जात असला तरी, रिएक्ट हुक्स एक अधिक संक्षिप्त आणि कार्यात्मक दृष्टिकोन देतात. आपण एक पुन्हा वापरण्यायोग्य useErrorBoundary हुक तयार करू शकतो जो एरर हँडलिंग लॉजिकला सामावून घेतो आणि रिसोर्स लोडिंग दरम्यान चुका होण्याची शक्यता असलेल्या कंपोनेंट्सना रॅप (wrap) करण्याचा सोयीस्कर मार्ग प्रदान करतो.
एक कस्टम useErrorBoundary हुक तयार करणे
येथे useErrorBoundary हुकचे एक उदाहरण आहे:
import { useState, useCallback } from 'react';
function useErrorBoundary() {
const [error, setError] = useState(null);
const resetError = useCallback(() => {
setError(null);
}, []);
const captureError = useCallback((e) => {
setError(e);
}, []);
const ErrorBoundary = useCallback(({ children, fallback }) => {
if (error) {
return fallback ? fallback : An error occurred: {error.message || String(error)};
}
return children;
}, [error]);
return { ErrorBoundary, captureError, error, resetError };
}
export default useErrorBoundary;
स्पष्टीकरण:
useState: आपण एरर स्टेट व्यवस्थापित करण्यासाठीuseStateवापरतो. हे सुरुवातीला एररलाnullवर सेट करते.useCallback: आपणresetErrorआणिcaptureErrorफंक्शन्स मेमोइझ (memoize) करण्यासाठीuseCallbackवापरतो. जर ही फंक्शन्स प्रॉप्स म्हणून पास केली जात असतील तर अनावश्यक री-रेंडर्स टाळण्यासाठी ही एक चांगली प्रथा आहे.ErrorBoundaryकंपोनेंट: हाuseCallbackसह तयार केलेला एक फंक्शनल कंपोनेंट आहे जोchildrenआणि एक पर्यायीfallbackप्रॉप घेतो. जर स्टेटमध्ये एरर असेल, तर ते प्रदान केलेलाfallbackकंपोनेंट किंवा डीफॉल्ट एरर मेसेज रेंडर करते. अन्यथा, ते चिल्ड्रन रेंडर करते. हे आपल्या एरर बाउंड्री म्हणून काम करते. डिपेंडेंसी ॲरे `[error]` हे सुनिश्चित करते की `error` स्टेट बदलल्यावर ते पुन्हा रेंडर होईल.captureErrorफंक्शन: हे फंक्शन एरर स्टेट सेट करण्यासाठी वापरले जाते. आपण रिसोर्सेस लोड करताना यालाtry...catchब्लॉकमध्ये कॉल कराल.resetErrorफंक्शन: हे फंक्शन एरर स्टेट क्लिअर करते, ज्यामुळे कंपोनेंटला त्याचे चिल्ड्रन पुन्हा रेंडर करण्याची (संभाव्यतः रिसोर्स लोडिंग पुन्हा प्रयत्न करण्याची) परवानगी मिळते.
एरर हँडलिंगसह रिसोर्स लोडिंग लागू करणे
आता, रिसोर्स लोडिंगमधील चुका हाताळण्यासाठी या हुकचा वापर कसा करायचा ते पाहूया. एका एपीआयवरून वापरकर्त्याचा डेटा मिळवणाऱ्या कंपोनेंटचा विचार करा:
import React, { useState, useEffect } from 'react';
import useErrorBoundary from './useErrorBoundary';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const { ErrorBoundary, captureError, error, resetError } = useErrorBoundary();
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setUser(data);
} catch (e) {
captureError(e);
}
};
fetchData();
}, [userId, captureError]);
if (error) {
return (
Failed to load user data. {user.name}
Email: {user.email}
{/* Other user details */}स्पष्टीकरण:
- आपण
useErrorBoundaryहुक इम्पोर्ट करतो. - आपण
ErrorBoundaryकंपोनेंट,captureErrorफंक्शन,errorस्टेट, आणिresetErrorफंक्शन मिळवण्यासाठी हुकला कॉल करतो. useEffectहुकमध्ये, आपण एपीआय कॉललाtry...catchब्लॉकमध्ये रॅप करतो.- जर एपीआय कॉल दरम्यान एरर आली, तर आपण एरर स्टेट सेट करण्यासाठी
captureError(e)कॉल करतो. - जर
errorस्टेट सेट असेल, तर आपणErrorBoundaryकंपोनेंट रेंडर करतो. आपण एक कस्टमfallbackप्रॉप देतो जो एक एरर मेसेज आणि एक "Retry" बटण दाखवतो. बटणावर क्लिक केल्यानेresetErrorकॉल होतो, ज्यामुळे एरर स्टेट क्लिअर होते, एक री-रेंडर ट्रिगर होते आणि डेटा मिळवण्याचा दुसरा प्रयत्न केला जातो. - जर कोणतीही एरर आली नसेल आणि वापरकर्त्याचा डेटा लोड झाला असेल, तर आपण वापरकर्त्याच्या प्रोफाइलचे तपशील रेंडर करतो.
विविध प्रकारच्या रिसोर्स लोडिंग चुका हाताळणे
वेगवेगळ्या प्रकारच्या रिसोर्स लोडिंग चुकांसाठी वेगवेगळ्या हाताळणी धोरणांची आवश्यकता असू शकते. येथे काही सामान्य परिस्थिती आणि त्या कशा हाताळायच्या हे दिले आहे:
नेटवर्क एरर्स
जेव्हा क्लायंट सर्व्हरशी कनेक्ट होऊ शकत नाही (उदा. नेटवर्क बंद पडल्यामुळे किंवा सर्व्हर डाउनटाइममुळे) तेव्हा नेटवर्क एरर्स येतात. वरील उदाहरण आधीच `response.ok` वापरून मूलभूत नेटवर्क एरर्स हाताळते. आपण अधिक अत्याधुनिक एरर डिटेक्शन जोडू शकता, उदाहरणार्थ:
//Inside the fetchData function
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
// Consider adding specific error code handling
if (response.status === 404) {
throw new Error("User not found");
} else if (response.status >= 500) {
throw new Error("Server error. Please try again later.");
} else {
throw new Error(`HTTP error! status: ${response.status}`);
}
}
const data = await response.json();
setUser(data);
} catch (error) {
if (error.message === 'Failed to fetch') {
// Likely a network error
captureError(new Error('Network error. Please check your internet connection.'));
} else {
captureError(error);
}
}
या प्रकरणात, आपण वापरकर्त्याला एक संदेश दाखवू शकता की नेटवर्क कनेक्टिव्हिटी समस्या आहे आणि त्यांना त्यांचे इंटरनेट कनेक्शन तपासण्यास सुचवू शकता.
एपीआय एरर्स
जेव्हा सर्व्हर एरर रिस्पॉन्स देतो (उदा. 400 Bad Request किंवा 500 Internal Server Error) तेव्हा एपीआय एरर्स येतात. वर दाखवल्याप्रमाणे, आपण `response.status` तपासू शकता आणि या चुका योग्यरित्या हाताळू शकता.
डेटा पार्सिंग एरर्स
जेव्हा सर्व्हरकडून आलेला रिस्पॉन्स अपेक्षित फॉरमॅटमध्ये नसतो आणि पार्स केला जाऊ शकत नाही (उदा. अवैध JSON) तेव्हा डेटा पार्सिंग एरर्स येतात. आपण response.json() कॉलला try...catch ब्लॉकमध्ये रॅप करून या चुका हाताळू शकता:
//Inside the fetchData function
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setUser(data);
} catch (error) {
if (error instanceof SyntaxError) {
captureError(new Error('Failed to parse data from server.'));
} else {
captureError(error);
}
}
इमेज लोडिंग एरर्स
इमेज लोडिंगसाठी, आपण <img> टॅगवरील onError इव्हेंट हँडलर वापरू शकता:
function MyImage({ src, alt }) {
const { ErrorBoundary, captureError } = useErrorBoundary();
const [imageLoaded, setImageLoaded] = useState(false);
const handleImageLoad = () => {
setImageLoaded(true);
};
const handleImageError = (e) => {
captureError(new Error(`Failed to load image: ${src}`));
};
return (
Failed to load image.